#include <BRepPrimAPI_MakeBox.hxx>
#include <vtkRenderWindow.h>
#include <vtkNew.h>
#include <vtkInteractorStyleTrackballCamera.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkPolyDataMapper.h>
#include <IVtkTools_ShapeDataSource.hxx>
#include <IVtkTools_ShapePicker.hxx>
#include "QIVtkSelectionPipeline.h"
#include "QVTKInteractorStyle.h"
#include "vtkCamera.h"
#include "vtkFloatArray.h"
#include "vtkPolyData.h"
#include "vtkSphereSource.h"
#include "vtkPointData.h"
#include "IVtkTools_SubPolyDataFilter.hxx"
#include <BRepBuilderAPI_Transform.hxx>
#include <GC_MakeArcOfCircle.hxx>

int main()
{
	// pipeline用法
	if(0)
	{
		BRepPrimAPI_MakeBox box(1, 1, 1);
		const TopoDS_Shape& shape = box.Shape();

		vtkNew<vtkRenderWindow>  renderWindow;
		vtkNew<vtkRenderer> renderer;
		renderWindow->AddRenderer(renderer);

		vtkNew<vtkRenderWindowInteractor> windowInteractor;
		windowInteractor->SetRenderWindow(renderWindow);

		QIVtkSelectionPipeline* actor1 = new QIVtkSelectionPipeline(shape, 1);
		actor1->AddToRenderer(renderer);

		gp_Vec translationVec(1, 0, 0);
		gp_Trsf translation;
		translation.SetTranslation(translationVec);
		BRepBuilderAPI_Transform transformer(shape, translation);
		QIVtkSelectionPipeline* actor2 = new QIVtkSelectionPipeline(transformer.Shape(), 2);
		actor2->AddToRenderer(renderer);

		vtkSmartPointer<QVTKInteractorStyle> m_pickInteractorStyle = vtkSmartPointer<QVTKInteractorStyle>::New();
		vtkSmartPointer<IVtkTools_ShapePicker> m_shapePicker = vtkSmartPointer<IVtkTools_ShapePicker>::New();
		// Setup IVtk Shape picker
		m_shapePicker->SetRenderer(renderer);
		m_shapePicker->SetTolerance(0.1);
		m_pickInteractorStyle->setVTKRenderWindow(renderWindow);
		m_pickInteractorStyle->setOcctPicker(m_shapePicker);


		windowInteractor->SetInteractorStyle(m_pickInteractorStyle);
		m_pickInteractorStyle->addPipeline(actor1, actor1->GetShapeID());
		m_pickInteractorStyle->addPipeline(actor2, actor2->GetShapeID());

		m_pickInteractorStyle->setSelectionMode(SM_Face);

		renderWindow->Render();
		windowInteractor->Start();
	}

	// lookupTable用法->球形每个顶点不同颜色
	if(0)
	{
		// 创建一个球体数据源
		vtkSmartPointer<vtkSphereSource> sphereSource = vtkSmartPointer<vtkSphereSource>::New();
		sphereSource->Update();

		// 获取球体的点数
		vtkSmartPointer<vtkPolyData> polyData = sphereSource->GetOutput();
		int numberOfPoints = polyData->GetNumberOfPoints();

		// 创建标量数据数组，每个顶点赋予不同的标量值
		vtkSmartPointer<vtkFloatArray> scalars = vtkSmartPointer<vtkFloatArray>::New();
		for (int i = 0; i < numberOfPoints; ++i) {
			scalars->InsertNextValue(static_cast<float>(i) / numberOfPoints); // 每个点的标量值从0到1
		}
		polyData->GetPointData()->SetScalars(scalars);  // 将标量值关联到点数据

		// 创建一个 LookupTable，设置颜色范围
		vtkSmartPointer<vtkLookupTable> lookupTable = vtkSmartPointer<vtkLookupTable>::New();
		lookupTable->SetNumberOfTableValues(256);  // 设置颜色表的条目数
		lookupTable->SetRange(0.0, 1.0);           // 标量范围从0到1
		lookupTable->Build();

		// 创建 mapper 并设置 LookupTable
		vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
		mapper->SetInputData(polyData);
		mapper->SetLookupTable(lookupTable);
		mapper->SetScalarRange(0.0, 1.0);  // 设置标量范围，这里和 LookupTable 的范围一致

		// 创建 actor 和渲染器
		vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
		actor->SetMapper(mapper);

		vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
		vtkSmartPointer<vtkRenderWindow> renderWindow = vtkSmartPointer<vtkRenderWindow>::New();
		renderWindow->AddRenderer(renderer);

		vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
		renderWindowInteractor->SetRenderWindow(renderWindow);

		renderer->AddActor(actor);
		renderer->SetBackground(1, 1, 1); // 设置白色背景

		renderWindow->Render();
		renderWindowInteractor->Start();

		return 0;
	}

	// IVtkTools_DisplayModeFilter用法
	if(0)
	{
		BRepPrimAPI_MakeBox box(2, 2, 2);
		const TopoDS_Shape& shape = box.Shape();

		vtkNew<vtkRenderWindow> renderWindow;
		vtkNew<vtkRenderer> render;
		renderWindow->AddRenderer(render);

		vtkNew<vtkRenderWindowInteractor> iren;
		vtkNew<vtkInteractorStyleTrackballCamera> istyle;

		iren->SetRenderWindow(renderWindow);
		iren->SetInteractorStyle(istyle);

		vtkNew<IVtkTools_ShapeDataSource> occSource;
		occSource->SetShape(new IVtkOCC_Shape(shape));

		IVtkTools_DisplayModeFilter* PolyDataFilter = IVtkTools_DisplayModeFilter::New();
		PolyDataFilter->AddInputConnection(occSource->GetOutputPort());
		PolyDataFilter->SetDisplayMode(IVtk_DisplayMode::DM_Wireframe);

		vtkNew<vtkPolyDataMapper> mapper;
		mapper->SetInputConnection(PolyDataFilter->GetOutputPort());

		vtkNew<vtkActor> actor;
		actor->SetMapper(mapper);
		render->AddActor(actor);

		iren->Initialize();
		iren->Start();

		return 0;
	}
	//测试构建空心实体
	if (1) {
		BRepPrimAPI_MakeBox box(1, 1, 1);
		const TopoDS_Shape& shape = box.Shape();
		vtkNew<vtkRenderWindow>  renderWindow;
		vtkNew<vtkRenderer> renderer;
		renderWindow->AddRenderer(renderer);
		vtkNew<vtkRenderWindowInteractor> windowInteractor;
		windowInteractor->SetRenderWindow(renderWindow);
		QIVtkSelectionPipeline* actor1 = new QIVtkSelectionPipeline(shape, 1);
		actor1->AddToRenderer(renderer);
		vtkSmartPointer<QVTKInteractorStyle> m_pickInteractorStyle = vtkSmartPointer<QVTKInteractorStyle>::New();
		vtkSmartPointer<IVtkTools_ShapePicker> m_shapePicker = vtkSmartPointer<IVtkTools_ShapePicker>::New();
		// Setup IVtk Shape picker
		m_shapePicker->SetRenderer(renderer);
		m_shapePicker->SetTolerance(0.1);
		m_pickInteractorStyle->setVTKRenderWindow(renderWindow);
		m_pickInteractorStyle->setOcctPicker(m_shapePicker);
		windowInteractor->SetInteractorStyle(m_pickInteractorStyle);
		m_pickInteractorStyle->addPipeline(actor1, actor1->GetShapeID());
		m_pickInteractorStyle->setSelectionMode(SM_Face);



		/*BRepOffsetAPI_MakeThickSolidByJoin()
		参数：原始实体
		，待删除面集合：这些面必须是闭合面
		，容差：两壁 W1 和 W2 之间的厚度（距离 D）
		移除原始实体待删除面后得到壁1，之后根据厚度D来得到壁2（如果 D 为正，则 W2 将位于初始实体外部，否则它将位于内部）
		之后根据W1和W2计算得到空心实体*/

		renderWindow->Render();
		windowInteractor->Start();
	}
	if (1) {
		//构建圆弧：通过三个点，最后一个点为中间点
		//Standard_EXPORT GC_MakeArcOfCircle(const gp_Pnt& P1, const gp_Pnt& P2, const gp_Pnt& P3);
	}
	return 0;
}